1. /* sdfhypbl.cpp by K.Tsuru */
  2. // function ID 3300 DRADIX
  3. /*****************************************************************************
  4. SDouble class
  5. It provides the hyperbolic functions.
  6. cosh x for func == COSH_CALC, sinh x for func == SINH_CALC
  7. pfSeries = CoshSeries or SinhSeries(function pointer)
  8. Both functions have nearly the same algorism, then bounded in one program for
  9. an easy maintenance.When only one of them(Sinh or Cosh) is used, in order to
  10. avoid to link another one you must pass the function pointer of the series
  11. function for a small |x|.
  12. ******************************************************************************/
  13. #ifndef SN_H
  14. #include "sn.h"
  15. #endif
  16. SDouble Hyperbolic(const SDouble& x, int func, SDouble (*pfSeries)(const SDouble& x)){
  17. if(!x.Sign(3300)){
  18. if(func == COSH_CALC) return 1.0;
  19. return 0.0;
  20. }
  21. const double XBySeries = 8.0; //When |x| is less than this value it uses the series.
  22. const uint figBySeries = 16u; //When the figures of 'x' is less than this value it uses the series.
  23. const double xMax = (double)DFIGURES*M_LN10*(double)DRADIX_EXP_MAX; // = 301759.17...
  24. //check the argument, e^x < DRADIX^DRADIX_EXP_MAX
  25. double xD = fabs( doubleD(x, 0) );
  26. if(xD > xMax) x.SetError(x.OVERFLOW_ERR, "Hyperbolic", 3300);
  27. //When 'x' has a short and small value, it is fast to use the series.
  28. uint fig = x.Last() - x.First() + 1u;
  29. int xe = x.NetRdxExp(), series = 0;
  30. // |x| is less than XBySeries.
  31. if( (fig <= figBySeries) && (xD < XBySeries) ) series = 1;
  32. //When |x| << 1.0, the calculation "sinh x" by "Exp(x)" yields a cancelation.
  33. if(xe < 0) series = 1; // |x| < 1/DRADIX
  34. if(series) return (*pfSeries)(x); //The series of "sinh" and "cosh" rapidly converges.
  35. // |x| >= 1/DRADIX
  36. SDouble r, dr;
  37. r = Exp(Dabs(x)); //r = e^|x|
  38. long ef=(long)x.MaxSize() - (long)r.NetRdxExp();
  39. if(ef<=0) dr.SetZero(); //(1/r) is much less than r.
  40. else {
  41. RealSize C;
  42. C.SetEffFig(uint(ef)); //It can decrease the effective figures.
  43. dr = DReciprocal(r); //dr = 1/(e^|x|)
  44. C.SetEffFig(0);
  45. }
  46. if(func == COSH_CALC) r += dr; //cosh x
  47. else { //sinh x
  48. r -= dr;
  49. // A bug was fixed on March 13, 2001.
  50. if(x.Sign() <0) r.ChangeSign(); //This statement was lacked.
  51. }
  52. r = DsDiv(r, 2); //r /=2;
  53. return r;
  54. }

sdfhypbl.cpp : last modifiled at 2015/06/09 15:48:24(2,314 bytes)
created at 2017/10/07 10:22:50
The creation time of this html file is 2017/10/07 11:29:39 (Sat Oct 07 11:29:39 2017).